home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 483 / mkrscsrc / tree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-29  |  14.8 KB  |  579 lines

  1. #include "stdio.h"
  2. #include "gemdefs.h"
  3. #include "obdefs.h"
  4. #include "osbind.h"
  5. #include "mkrsc.h"
  6. #include "globals.h"
  7. #include "strings.h"
  8.  
  9.  
  10. /*    trav_tree travels through an object tree from node 0 following
  11.     the subtrees until it returns to node 0.  It records the index
  12.     number of each object in the array 'order'.  It returns the
  13.     total number of objects in the tree.  Objects that are encountered
  14.     more than once (subtree nodes) are only entered into 'order' the
  15.     first time that they are encountered.
  16. */
  17.  
  18.  
  19. int trav_tree(tree,order)
  20.     OBJECT    *tree;
  21.     int        order[MAXONUM];
  22. {
  23.     int index, pos, head, next;
  24.     
  25.  
  26.     index = 0;
  27.     pos = 0;
  28.     order[index] = 0;
  29.     
  30.     do
  31.     {
  32.         head = tree[pos].ob_head;
  33.         next = tree[pos].ob_next;
  34.         if( (head > -1 ) && (not_already(order,index,head)))    
  35.         {    order[index+1] = head;
  36.             pos = head;
  37.             index++;
  38.         }
  39.         else if ( (next > -1) && (not_already(order,index,next)) )
  40.         {    order[index+1] = next;
  41.             pos = next;
  42.             index++;
  43.         }
  44.         else if (next > -1)
  45.             pos = next;
  46.         else return(1);
  47.     }
  48.     while (tree[pos].ob_next > -1);
  49.     return(index+1);
  50. }
  51.  
  52. int not_already(order, index, head)
  53.     int *order, index, head;
  54. {
  55.     int i;
  56.  
  57.     for (i=0;i < index+1;i++)
  58.     {    if (order[i] == head)
  59.             return(0);
  60.     }
  61.     return(1);
  62. }
  63.     
  64. /*    ord_tree() travels an object tree and copies the objects to a 
  65.     temporary tree in the proper order.  It then resets all of the 
  66.     ob_next, ob_head and ob_tail pointers properly and recopies
  67.     the final tree back into the original object tree array.
  68.     I have rearranged the string, tedinfo etc arrays.  Lastly I reset
  69.     thefrontwin->inwindow->count in case there have been deletions
  70. */
  71.  
  72. int ord_tree()
  73. {
  74.     int numobjs, i;
  75.     int    order[MAXONUM];
  76.     OBJECT *tmptree;
  77.     objtreeptr    temp, thetree;
  78.     OBJECT *inwinptr;
  79.  
  80.     temp  = (objtreeptr) malloc(sizeof(objtree));
  81.  
  82.     tmptree = temp->objt;
  83.  
  84.     thetree = thefrontwin->inwindow;
  85.  
  86.     inwinptr = thetree->objt;
  87.     
  88.     numobjs = trav_tree(inwinptr,order);
  89.  
  90.     thefrontwin->inwindow->count = numobjs-1;
  91.  
  92.     for (i=0;i<numobjs;i++)
  93.     if(i != order[i])        /* don't copy identical things    */
  94.         tmptree[i] = inwinptr[order[i]];                        /* objt    */
  95.  
  96.     for (i=0;i<numobjs;i++)
  97.     if(i != order[i])
  98.         inwinptr[i] = tmptree[i];                                /*    objt */
  99.  
  100.     for (i=0;i<numobjs;i++)
  101.     {    inwinptr[i].ob_next = newpos(inwinptr[i].ob_next,numobjs,order);
  102.         inwinptr[i].ob_head = newpos(inwinptr[i].ob_head,numobjs,order);
  103.         inwinptr[i].ob_tail = newpos(inwinptr[i].ob_tail,numobjs,order);
  104.     }
  105.  
  106.     for (i = 0; i < numobjs;i++)    
  107.     if(i != order[i])
  108.     {    bcopy(thetree->name[order[i]],temp->name[i],30);
  109.         bcopy(thetree->strings[order[i]],temp->strings[i],60);
  110.         bcopy(thetree->template[order[i]],temp->template[i],60);
  111.         bcopy(thetree->valid[order[i]],temp->valid[i],60);
  112.         temp->icblk[i] = thetree->icblk[order[i]];
  113.         temp->ti[i] = thetree->ti[order[i]];
  114.         temp->kind[i] = thetree->kind[order[i]];
  115.         temp->treelink[i] = thetree->treelink[order[i]];
  116.     }
  117.  
  118.     for (i = 0; i < numobjs;i++)
  119.     if(i != order[i])
  120.     {    bcopy(temp->name[i],thetree->name[i],30);
  121.         bcopy(temp->strings[i],thetree->strings[i],60);
  122.         bcopy(temp->template[i],thetree->template[i],60);
  123.         bcopy(temp->valid[i],thetree->valid[i],60);
  124.         thetree->icblk[i] = temp->icblk[i];
  125.         thetree->ti[i] = temp->ti[i];
  126.         thetree->kind[i] = temp->kind[i];
  127.         thetree->treelink[i] = temp->treelink[i];
  128.  
  129.         switch (thetree->objt[i].ob_type)
  130.         {
  131.             case G_TEXT        :
  132.             case G_BOXTEXT    :
  133.             case G_FTEXT    :
  134.             case G_FBOXTEXT    : 
  135.                 thetree->ti[i].te_ptext = (char *)thetree->strings[i];
  136.                 thetree->ti[i].te_ptmplt = (char *)thetree->template[i];
  137.                 thetree->ti[i].te_pvalid = (char *)thetree->valid[i];
  138.                 inwinptr[i].ob_spec = (char *)(&thetree->ti[i]);
  139.                 break;
  140.             case G_BUTTON    :
  141.             case G_STRING    :
  142.             case G_TITLE    :
  143.                 inwinptr[i].ob_spec = (char *)thetree->strings[i];
  144.                 break;
  145.             case G_ICON        :
  146.                 thetree->icblk[i].ib_ptext = (char *)thetree->name[i];
  147.                 inwinptr[i].ob_spec = (char *)(&thetree->icblk[i]);
  148.                 break;
  149.         }        
  150.     }
  151.     free((char *)temp);
  152. }    
  153.  
  154.  
  155. int newpos(index,numobjs, order)
  156.     int index, numobjs;
  157.     int order[MAXONUM];
  158. {
  159.     int i;
  160.  
  161.     for (i=0;i < numobjs; i++)
  162.         if (order[i] == index)
  163.             return(i);
  164.     return(-1);
  165. }
  166.  
  167. /*     in_ttl() puts new title entries onto the menu bar at the correct
  168.     position given by x,y.  It makes a list of the index numbers of
  169.     the current title numbers in ttls[] and the corresponding menu
  170.     boxes in boxes[].  It uses these to position the new title and
  171.     menu box entry.
  172. */
  173.  
  174. int in_ttl(x,y,paste)
  175.     int x,y,paste;
  176. {
  177.     int    ttls[50], boxes[50], count, xoff, yoff;
  178.     int i, head, tail, next, tparent, bparent, num;
  179.     OBJECT *objptr, *tree;
  180.     objtreeptr thetree;
  181.     windowptr    thewin;
  182.  
  183.     thewin = thefrontwin;
  184.  
  185.     thetree = thefrontwin->inwindow;
  186.     tree = thetree->objt;
  187.  
  188.     thefrontwin->inwindow->mbox = 0;
  189.  
  190.     for(i=0;i<(thefrontwin->inwindow->count + 1);i++)
  191.                 if(tree[i].ob_state & SELECTED)
  192.                     tree[i].ob_state &= ~SELECTED;
  193.  
  194.     objc_offset(tree,2,&xoff,&yoff);
  195.     x = x - xoff;
  196.     y = y - yoff;
  197.  
  198. /* handy pointer    */
  199.     num = ++thetree->count;
  200.  
  201.     if(paste)    
  202.     {
  203.             thefrontwin->inwindow->kind[num] = tempo.okind;
  204.             strcpy(thefrontwin->inwindow->name[num],tempo.oname);
  205.             strcpy(thefrontwin->inwindow->strings[num],tempo.ostrings);
  206.             thefrontwin->inwindow->objt[num] = tempo.oobjt;
  207.     }
  208.     else
  209.     {
  210. /* copy the title into the object tree array in thetree struct */
  211.  
  212.     thetree->objt[num] = onleft[TITLE];
  213.  
  214. /* copy the oject index from onleft tree into 'kind'    */
  215.  
  216.     thetree->kind[num] = TITLE;
  217.     thetree->name[num][0] = NULL;
  218.  
  219. /* copy the TITLE string into the new object string space */
  220.  
  221.     strcpy(thetree->strings[num], onleft[TITLE].ob_spec);
  222.     }
  223.     thetree->objt[num].ob_spec = thetree->strings[num];
  224.  
  225. /* set up a handy ptr */
  226.     objptr = &thetree->objt[num];
  227.  
  228. /* clear the pointers for the new object  */
  229.  
  230.     objptr->ob_next = -1;
  231.     objptr->ob_head = -1;
  232.     objptr->ob_tail = -1;
  233.  
  234.     tparent = 2;
  235.     head = tree[tparent].ob_head;
  236.     
  237.     ttls[0]= head;
  238.     for(next=head,i=1;(next!=2 && i < 500);next=tree[next].ob_next,i++)
  239.         ttls[i] = tree[next].ob_next;
  240.     count = i-1;    
  241.  
  242. /*    ttls contains the list of title index numbers
  243.     and boxes contains the list of menu boxes
  244. */
  245.  
  246.     bparent = tree[1].ob_next;
  247.     head = tree[bparent].ob_head;
  248.     
  249.     boxes[0] = head;
  250.     for(next=head,i=1;(next!=bparent && i < 500);next=tree[next].ob_next,i++)
  251.         boxes[i] = tree[next].ob_next;
  252.         
  253. /* insert the new title into the list of children */
  254.  
  255.     for(i=1;i<count;i++)
  256.         if(tree[ttls[i]].ob_x > x)
  257.              break;
  258.  
  259.     objptr->ob_next = tree[ttls[i-1]].ob_next;
  260.     if(objptr->ob_next == tparent)
  261.         tree[tparent].ob_tail = num;
  262.     tree[ttls[i-1]].ob_next = num;
  263.  
  264. /* put a new menu box into the tree    */
  265.  
  266.     thetree->objt[++thetree->count] = onleft[MENUBOX];
  267.     
  268. /* handy pointer, as before    */
  269.     num = thetree->count;
  270.  
  271. /* set up a handy ptr, as before     */
  272.     objptr = &thetree->objt[num];
  273.  
  274. /* widen the box a bit    */
  275.  
  276.     objptr->ob_width = 90;
  277.  
  278. /* insert new box into list of children    */
  279.  
  280.     objptr->ob_next = tree[boxes[i-1]].ob_next;
  281.     if(objptr->ob_next == bparent)
  282.         tree[bparent].ob_tail = num;
  283.     tree[boxes[i-1]].ob_next = num;
  284.  
  285. /* now rebuild the tree in perfect order and tidy up x values    */
  286.  
  287.     tidy_m();
  288. }
  289.  
  290.  
  291. int tidy_m()
  292. {
  293.     int    ttls[50], boxes[50], count;
  294.     int i, head, next, tparent, bparent, width;
  295.     int    cx, cy, cw, ch;
  296.     OBJECT *tree;
  297.     objtreeptr thetree;
  298.     windowptr    thewin;
  299.  
  300.     thewin = thefrontwin;
  301.  
  302.     thetree = thefrontwin->inwindow;
  303.     tree = thetree->objt;
  304.  
  305. /* now rebuild the tree in perfect order    */
  306.  
  307.     ord_tree();
  308.  
  309. /* clean up the x position of the new title and menu box
  310.     first rebuild ttls and boxes
  311. */
  312.     tparent = 2;
  313.     head = tree[tparent].ob_head;
  314.  
  315.     ttls[0]= head;
  316.     for(next=head,i=1;(next!=2 && i < 500);next=tree[next].ob_next,i++)
  317.         ttls[i] = tree[next].ob_next;
  318.     count = i-1;    
  319.  
  320. /*    ttls contains the list of title index numbers    */
  321.  
  322.     bparent = tree[1].ob_next;
  323.     head = tree[bparent].ob_head;
  324.     
  325.     boxes[0] = head;
  326.     for(next=head,i=1;(next!=bparent && i < 500);next=tree[next].ob_next,i++)
  327.         boxes[i] = tree[next].ob_next;
  328.  
  329. /* now fix x values */
  330.  
  331.     for(i=1;i<count;i++)
  332.     {tree[ttls[i]].ob_x = tree[ttls[i-1]].ob_x + tree[ttls[i-1]].ob_width;
  333.      tree[ttls[i]].ob_y = tree[ttls[0]].ob_y;    
  334.      tree[boxes[i]].ob_x = tree[ttls[i]].ob_x + tree[boxes[0]].ob_x;
  335.      tree[boxes[i]].ob_y = tree[boxes[0]].ob_y;
  336.     }
  337.  
  338. /* fix width of the box under the titles... object 2 in tree */
  339.  
  340.     for (i=0,width=0;i<count;i++)
  341.     width += tree[ttls[i]].ob_width;
  342.     tree[2].ob_width = width + 4;
  343.     
  344. }
  345.  
  346. /*     mv_ttl() moves a title from one position to another
  347.     it just unlinks an relinks the title and its associated
  348.     menu box to a new position in the list of children and then
  349.     tidies up the x values of the two lists of objects.
  350.     'index' is the index of the title in the menu tree.
  351. */
  352.  
  353. int mv_ttl(index,x,y)
  354.     int index,x,y;
  355. {
  356.     int    ttls[50], boxes[50], count, xoff, yoff;
  357.     int i, head, tail, next, tparent, bparent, num, imbox;
  358.     OBJECT *objptr, *tree;
  359.     objtreeptr thetree;
  360.     windowptr    thewin;
  361.  
  362.     thewin = thefrontwin;
  363.  
  364.     thetree = thefrontwin->inwindow;
  365.     tree = thetree->objt;
  366.  
  367.     thefrontwin->inwindow->mbox = 0;
  368.  
  369.     for(i=0;i<(thefrontwin->inwindow->count + 1);i++)
  370.                 if(tree[i].ob_state & SELECTED)
  371.                     tree[i].ob_state &= ~SELECTED;
  372.  
  373. /* tparent is parent of titles and bparent parent of menu boxes    */
  374.  
  375.         tparent = 2;
  376.         bparent = tree[1].ob_next;
  377.  
  378. /* find the index number of the menu box associated with title 'index'    */
  379.  
  380.         next = tree[bparent].ob_head;
  381.         for (i=0;i<index-tparent;i++)
  382.             {    imbox = next;
  383.                 next = tree[next].ob_next;
  384.             } 
  385.  
  386.     objc_offset(tree,2,&xoff,&yoff);
  387.     x = x - xoff;
  388.     y = y - yoff;
  389.  
  390. /*    ttls contains the list of title index numbers
  391.     and boxes contains the list of menu boxes
  392. */
  393.  
  394.     head = tree[bparent].ob_head;
  395.     
  396.     boxes[0] = head;
  397.     for(next=head,i=1;(next!=bparent && i < 150);next=tree[next].ob_next,i++)
  398.         boxes[i] = tree[next].ob_next;
  399.     count = i-1;    
  400.         
  401. /* delete the title from the list of titles    */
  402.  
  403.     tree[index-1].ob_next = tree[index].ob_next;
  404.     if(tree[index].ob_next == tparent)
  405.         tree[tparent].ob_tail = index-1;
  406.  
  407. /*    delete the associated menu box    */
  408.  
  409.     for(i=0; i<count;i++)
  410.         if (boxes[i] == imbox)
  411.             break;
  412.  
  413.     tree[boxes[i-1]].ob_next = tree[imbox].ob_next;
  414.     if(tree[imbox].ob_next == bparent)
  415.         tree[bparent].ob_tail = boxes[i-1];
  416.     
  417. /* rebuild boxes and ttls  */
  418.  
  419.     head = tree[tparent].ob_head;
  420.     
  421.     ttls[0]= head;
  422.     for(next=head,i=1;(next!=2 && i < 150);next=tree[next].ob_next,i++)
  423.         ttls[i] = tree[next].ob_next;
  424.     count = i-1;    
  425.  
  426.     head = tree[bparent].ob_head;
  427.     
  428.     boxes[0] = head;
  429.     for(next=head,i=1;(next!=bparent && i < 150);next=tree[next].ob_next,i++)
  430.         boxes[i] = tree[next].ob_next;
  431.         
  432. /* insert the new title into the list of children */
  433.  
  434.     for(i=1;i<count;i++)
  435.         if(tree[ttls[i]].ob_x > x)
  436.              break;
  437.  
  438.     tree[index].ob_next = tree[ttls[i-1]].ob_next;
  439.     if(tree[index].ob_next == tparent)
  440.         tree[tparent].ob_tail = index;
  441.     tree[ttls[i-1]].ob_next = index;
  442.  
  443. /* insert  box into new position    */
  444.  
  445.     tree[imbox].ob_next = tree[boxes[i-1]].ob_next;
  446.     if(tree[imbox].ob_next == bparent)
  447.         tree[bparent].ob_tail = imbox;
  448.     tree[boxes[i-1]].ob_next = imbox;
  449.  
  450. /* now rebuild the tree in perfect order and tidy up x values    */
  451.  
  452.     tidy_m();
  453. }
  454.  
  455. int name_obj()
  456. {
  457.     OBJECT *inwinptr;
  458.     int        i, result;
  459.     char newname[30];
  460.  
  461.  
  462. /*    Set up handy pointer to right window object tree    */
  463.  
  464.         inwinptr = thefrontwin->inwindow->objt;
  465.  
  466. /* point the tedinfo of the tree namer dialog to newname    */
  467.  
  468.         ((TEDINFO *)namobjt[NOEDIT].ob_spec)->te_ptext = newname;
  469.  
  470. /* point the tedinfo of the tree namer dialog to newname    */
  471.  
  472.         ((TEDINFO *)oldtree[NTEDIT].ob_spec)->te_ptext = newname;
  473.  
  474.     thefrontwin->saved = FALSE;
  475.  
  476.     if(thefrontwin->inwindow == &thefrontwin->maintree)
  477.      {    for(i=1;i<thefrontwin->inwindow->count+1;i++)
  478.         if(inwinptr[i].ob_state & SELECTED)
  479.         {    /* oldtree is object from RSC  */
  480.  
  481.             strcpy(newname,thefrontwin->inwindow->name[i]);
  482.  
  483.             oldtree[OTMENU].ob_state = NORMAL;
  484.             oldtree[OTDIALOG].ob_state = NORMAL;
  485.             oldtree[OTUNKNOW].ob_state = NORMAL;
  486.  
  487.             switch (thefrontwin->inwindow->kind[i])
  488.             {
  489.                 case TMENU    :    oldtree[OTMENU].ob_state = SELECTED;
  490.                                 break;
  491.                 case TDIALOG:    oldtree[OTDIALOG].ob_state = SELECTED;
  492.                                 break;
  493.                 case TUNKNOWN:    oldtree[OTUNKNOW].ob_state = SELECTED;
  494.                                 break;
  495.             }
  496.             result = do_dialog(oldtree,0);
  497.             oldtree[OTOK].ob_state = NORMAL;
  498.             oldtree[OTCANCEL].ob_state = NORMAL;
  499.             if(result == OTCANCEL)
  500.                 return;
  501.             else
  502.             { result = thefrontwin->inwindow->kind[i];
  503.               if (oldtree[OTMENU].ob_state & SELECTED) result = TMENU;
  504.               else if (oldtree[OTDIALOG].ob_state & SELECTED) result = TDIALOG;
  505.               else if (oldtree[OTUNKNOW].ob_state & SELECTED) result = TUNKNOWN;
  506.               if(thefrontwin->inwindow->kind[i] != result)
  507.                 {    thefrontwin->inwindow->kind[i] = result;
  508.                     thefrontwin->inwindow->treelink[i]->kind[0] = result;
  509.     /* copy the new icon's ICONBLK to the maintree array of ICONBLKs    */
  510.  
  511.                     thefrontwin->inwindow->icblk[i] =
  512.                                  *((ICONBLK *)(treicont[result].ob_spec));
  513.     /*  and point ICONBLK ptext to 'name' in maintree struct */
  514.  
  515.                     thefrontwin->inwindow->icblk[i].ib_ptext = 
  516.                                 thefrontwin->inwindow->name[i];
  517.                 }
  518.             oldtree[OTMENU].ob_state = NORMAL;
  519.             oldtree[OTDIALOG].ob_state = NORMAL;
  520.             oldtree[OTUNKNOW].ob_state = NORMAL;
  521.             if(strcmp(newname,thefrontwin->inwindow->name[i]) == 0)
  522.                  return;
  523.             if (check_name(newname) == 1)
  524.                     strcpy(thefrontwin->inwindow->name[i],newname);
  525.             return;
  526.             }
  527.         }  /*  end of 'if icon selected in maintree'    */
  528.     }    /*  end of 'if its the manitree'    */
  529.     else    /* must be a subtree    */
  530.         {for(i=1;i<thefrontwin->inwindow->count+1;i++)
  531.             if(inwinptr[i].ob_state & SELECTED)
  532.             {    /* namobjt is object from RSC  */
  533.     
  534.                 strcpy(newname,thefrontwin->inwindow->name[i]);
  535.  
  536.                 result = do_dialog(namobjt,0);
  537.                 namobjt[NOOK].ob_state = NORMAL;
  538.                 namobjt[NOCANCEL].ob_state = NORMAL;
  539.                 if(result == NOCANCEL)
  540.                     return;
  541.                 if(strcmp(newname,thefrontwin->inwindow->name[i]) == 0)
  542.                     return;
  543.                 if (check_name(newname) == 1)
  544.                     strcpy(thefrontwin->inwindow->name[i],newname);
  545.                 return;
  546.             }    
  547.         }
  548. }
  549. /*    check_name() returns 0 if an object or tree already has that
  550.     name... otherwise returns 1
  551. */
  552.  
  553. int check_name(str)
  554.     char *str;
  555. {
  556.         int i, j;    
  557.         objtreeptr    thesubtree;
  558.  
  559.         for(j=1;j<thefrontwin->maintree.count+1;j++)
  560.         {
  561.             if( (strlen(thefrontwin->maintree.name[j]) >0)
  562.                 && (strcmp(thefrontwin->maintree.name[j],str) == 0) )
  563.             {    form_alert(1, "[0][   There is already an  |   object with that name.   |   Choose another name.   ][ OK ]");
  564.                 return(0);
  565.             }
  566.             thesubtree = thefrontwin->maintree.treelink[j];
  567.             for(i=1;i<thesubtree->count+1;i++)
  568.             {
  569.                 if( (strlen(thesubtree->name[i]) >0)
  570.                     && (strcmp(thesubtree->name[i],str) == 0) )
  571.                 {    form_alert(1, "[0][   There is already an  |   object with that name.   |   Choose another name.   ][ OK ]");
  572.                     return(0);
  573.                 }
  574.             }
  575.         }
  576.         return(1);
  577. }
  578.     
  579.